﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ElevatorDispatching
{
    /// <summary>
    /// 楼层
    /// </summary>
    public class Floor : BindableBase, IEquatable<Floor>, IComparable<Floor>
    {
        /// <summary>
        /// 楼层编号，即第几层。不存在第 0 层。
        /// </summary>
        public int Id { get; }

        /// <summary>
        /// 楼层的相对高程
        /// </summary>
        public int Elevation => Id < 0 ? Id : Id - 1; // { -2, -1, -1, 1, 2 ... n } => { -2, -1, -1, 0, 1, ... n - 1 }

        /// <summary>
        /// 该楼层的向下一层
        /// </summary>
        public Floor LowerFloor { get; set; }

        /// <summary>
        /// 该楼层的向上一层
        /// </summary>
        public Floor UpperFloor { get; set; }

        /// <summary>
        /// 根据指定方向返回临近的一层
        /// </summary>
        /// <param name="direction">方向</param>
        /// <returns></returns>
        public Floor AdjacentFloor(Direction direction)
        {
            switch (direction)
            {
                case Direction.Down:
                    return LowerFloor;
                case Direction.Up:
                    return UpperFloor;
                default:
                    return null;
            }
        }

        public bool CanCallUp => UpperFloor != null;

        public bool CanCallDown => LowerFloor != null;

        public ButtonState CallUpButton { get; } = new ButtonState();

        public ButtonState CallDownButton { get; } = new ButtonState();

        /// <summary>
        /// 计算与另一楼层的相对距离
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int DistanceTo(Floor other) => Elevation > other.Elevation ? Elevation - other.Elevation : other.Elevation - Elevation;

        /// <summary>
        /// 计算与另一楼层的相对位置关系
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public Direction RelationWith(Floor other) => Id == other.Id ? Direction.Unspecified : Id > other.Id ? Direction.Up : Direction.Down;

        public Floor(int id)
        {
            if (id == 0) throw new ArgumentException("不存在第 0 层。");
            Id = id;
        }

        #region Helpers

        public bool Equals(Floor other) => other == null ? false : Id == other.Id;

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(this, obj)) return true;
            if (obj is Floor other) return Equals(other);
            return false;
        }

        public override int GetHashCode() => Id.GetHashCode();

        public int CompareTo(Floor other) => other == null ? throw new ArgumentNullException(nameof(other)) : Id.CompareTo(other.Id);

        public override string ToString() => $"第 {Id} 层";

        #endregion
    }
}
